home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <sys/stat.h>
-
- #ifndef INADDR_NONE
- #define INADDR_NONE -1
- #endif
-
- #include "tuner.h"
-
- static do_stationcall();
-
- char *dft_nets[] = { DFT_NETS, 0 };
-
- char radio_host[64]; /* Host where radio runs */
-
- int transmitter_port = CTLPRT_XMIT; /* Default control port for transmitters */
- int radio_port = CTLPRT_RADIO; /* Default control port for radios */
- struct sockaddr_in radio_addr; /* Address of our radio */
- struct sockaddr_in bcast_addrs[MAXNET]; /* Addresses of transmitters */
- int num_bcast_addrs = 0;
-
- struct station_info {
- char name[MAXNAME]; /* station name */
- int port; /* UDP broadcast port */
- int is_playing; /* 1 if currently transmitting */
- char logfile[MAXNAME]; /* Name of cdlog file */
- int since; /* Play time in minutes of current CD */
- char cdname[MAXNAME]; /* Current CD name */
- };
-
- struct station_info stations[MAXSTATION];
-
- char *station_names[MAXSTATION]; /* Hack. Points into stations array */
- int num_stations;
-
- char cur_name[MAXNAME];
- char cur_play[MAXNAME];
- char cur_time[MAXNAME];
- int cur_mute;
- int cur_port;
- int origtune = -1;
-
- int sock; /* Our socket */
- int sc_sock; /* Stationcall socket */
-
- char plbuf[MAXPLBUF][MAXNAME];
- char *playlist[MAXPLBUF];
- int num_playlist;
-
- init_io() {
- struct hostent *hent;
- int i;
-
- for( i=0; i<MAXSTATION; i++)
- station_names[i] = stations[i].name;
- /*XXX Process args */
- sock = opensock();
- sc_sock = openscsock();
-
- /*
- ** Divine address struct for radio station we're controlling.
- */
- if ( radio_host[0] == 0 ) {
- if ( gethostname(radio_host, sizeof(radio_host)) < 0 ) {
- perror("gethostname");
- exit(1);
- }
- }
- if ( (hent=gethostbyname(radio_host)) == 0 ) {
- #ifndef sun
- herror(radio_host);
- #else
- fprintf(stderr, "%s: Unknown host name\n", radio_host);
- #endif
- exit(1);
- }
- radio_addr.sin_family = AF_INET;
- radio_addr.sin_port = htons(radio_port);
- memcpy(&radio_addr.sin_addr, hent->h_addr, hent->h_length);
- /*
- ** Create list of broadcast addresses for locating stations.
- */
- if ( num_bcast_addrs == 0 ) {
- /*
- ** No addresses in arguments. Do the defaults.
- */
- char **p;
-
- for( p=dft_nets; *p; p++ )
- add_bcast_addr(*p);
- }
- /*
- ** Obtain station info and current station.
- */
- get_stations();
- get_curinfo();
- origstation = cur_tune;
- show_tuner(station_names, num_stations);
- show_tune(cur_tune, cur_name, cur_play, cur_time, cur_mute);
- show_playlist(playlist, num_playlist,1);
- watch_socket(sc_sock, do_stationcall);
- }
-
- get_stations() {
- int i;
- char *s;
- struct station_info *p;
-
- /*
- ** Clear old stations.
- */
- num_stations = 0;
- /*
- ** Broadcast info request.
- */
- for(i=0; i<num_bcast_addrs; i++)
- sendsock(sock, &bcast_addrs[i], "radio:s");
- /*
- ** Receive replies.
- */
- while ( (s=recvsock(sock)) ) {
- p = stations + num_stations;
- if ( parse_stationcall(p, s) )
- num_stations++;
- }
- }
-
- static
- do_stationcall(d1, d2, d3)
- int d1, d2, d3;
- {
- char *s;
- struct station_info sistr;
- int i;
-
- if ( (s=recvsock(sc_sock)) == NULL ) {
- fprintf(stderr, "tuner: stationcall event without data?\n");
- return;
- }
- if ( !parse_stationcall(&sistr, s) )
- return;
- for ( i=0; i<num_stations; i++)
- if ( stations[i].port == sistr.port ) {
- stations[i] = sistr;
- if ( sistr.port == cur_port ) {
- if( get_curinfo() )
- show_playlist(playlist, num_playlist,1);
- show_tune(cur_tune, cur_name, cur_play, cur_time, cur_mute);
- }
- return;
- }
- stations[num_stations] = sistr;
- num_stations++;
- show_tuner(station_names, num_stations);
- }
-
- parse_stationcall(p, s)
- struct station_info *p;
- char *s;
- {
- int port;
- char name[MAXNAME], logname[MAXNAME], cdname[MAXNAME];
- int is_playing, since;
- int i;
-
- is_playing = 1;
- since = -1;
- cdname[0] = '\0';
- logname[0] = '\0';
- i = sscanf(s, "radio:S:%[^:]:%d:%d:%[^:]:%d:%[^\n]", name, &port,
- &is_playing, logname, &since, cdname);
- if ( i >= 2 ) {
- strncpy(p->name, name, MAXNAME);
- p->port = port;
- p->is_playing = is_playing;
- strncpy(p->logfile, logname, MAXNAME);
- p->since = since;
- strncpy(p->cdname, cdname, MAXNAME);
- return 1;
- }
- fprintf(stderr, "Ill-formatted station call(%d): '%s'\n",i, s);
- return 0;
- }
-
- add_bcast_addr(addr)
- char *addr;
- {
- struct sockaddr_in *sp;
- unsigned long iaddr;
-
- sp = &bcast_addrs[num_bcast_addrs++];
- if ( (iaddr=inet_addr(addr)) == INADDR_NONE) {
- fprintf(stderr, "Ill-formatted address %s\n", addr);
- exit(1);
- }
-
- sp->sin_family = AF_INET;
- sp->sin_addr.s_addr = iaddr;
- sp->sin_port = htons(transmitter_port);
- }
-
- get_curinfo() {
- char *s;
- int n;
- int port, muteoff;
- int i;
- FILE *fp;
- char buf[128];
- int t;
-
- sendsock(sock, &radio_addr, "radio:i");
- num_playlist = 0;
- if ( s = recvsock(sock) ) {
- /*
- ** Parsing is funny, because older radio programs didn't have the
- ** mute feature (so only send a single number, the port).
- */
- n = sscanf(s, "radio:I:%d:%d", &muteoff, &port);
- if ( n == 0 ) {
- fprintf(stderr, "Funny reply from radio program: %s\n", s);
- return 1;
- }
- if ( n == 1 ) {
- port = muteoff;
- muteoff = 1;
- }
- cur_mute = !muteoff;
- cur_port = port;
- /*
- ** Try to find the corresponding station
- */
- for(i=0; i<num_stations; i++) {
- if ( cur_port == stations[i].port ) {
- cur_tune = i+1;
- strcpy(cur_name, stations[i].name);
- strcpy(cur_play, stations[i].cdname);
- t = stations[i].since / 60;
- if ( t == 0 )
- cur_time[0] = '\0';
- else if ( t < 60 )
- sprintf(cur_time, "%d minutes", t);
- else
- sprintf(cur_time, "%d hours", t/60);
- if ( !stations[i].is_playing )
- strcat(cur_time, "(Silent)");
- if ( stations[i].logfile[0] )
- return get_playlist(stations[i].logfile);
- return 1;
- }
- }
- if ( i == num_stations ) {
- /* Couldn't find the station number */
- cur_tune = 0;
- sprintf(cur_name, "Unknown (port %d)", cur_port);
- strcpy(cur_play, "?");
- strcpy(cur_time, "?");
- return 1;
- }
- }
- fprintf(stderr, "Warning: radio program not responding\n");
- strcpy(cur_name, "?");
- strcpy(cur_time, "?");
- strcpy(cur_play, "?");
- cur_tune = 0;
- return 1;
- }
-
- void
- do_tune(station)
- int station;
- {
- char buf[32];
-
- if ( station == 0 ) return;
- sprintf(buf, "radio:t:%d", stations[station-1].port);
- sendsock(sock, &radio_addr, buf);
- get_curinfo();
- show_tune(cur_tune, cur_name, cur_play, cur_time, cur_mute);
- show_playlist(playlist, num_playlist,1);
- }
-
- /*
- ** do_mute - Mute radio
- */
- void
- do_mute(onoff)
- int onoff;
- {
- sendsock(sock, &radio_addr, onoff?"radio:0":"radio:1");
- }
-
- /*
- ** get last MAXPLBUF entries of playlist file.
- */
- get_playlist(file)
- char *file;
- {
- FILE *fp;
- int i, j;
- static char fnbuf[MAXNAME];
- struct stat sb;
- static int mtime, saved_num_playlist;
-
- if ( strncmp(file, fnbuf, MAXNAME) == 0 ) {
- if ( stat(file, &sb) >= 0 && sb.st_mtime == mtime ) {
- /* Yes, cached copy still ok */
- num_playlist = saved_num_playlist;
- return 0;
- }
- }
-
- if ( (fp=fopen(file, "r")) == 0 )
- return;
-
- strncpy(fnbuf, file, MAXNAME);
- stat(file, &sb);
- mtime = sb.st_mtime;
-
- i = 0;
- while( (fgets(plbuf[i%MAXPLBUF], MAXNAME, fp)) ) i++;
- if ( i == 0 ) {
- num_playlist = 0;
- saved_num_playlist = 0;
- return;
- }
- i--;
-
- if ( i < MAXPLBUF ) {
- num_playlist = i+1;
- while ( i >= 0 ) {
- playlist[i] = plbuf[i];
- i--;
- }
- }
- else {
- for ( j=0; j<MAXPLBUF; j++) playlist[j] = plbuf[(i+j+1) % MAXPLBUF];
- num_playlist = MAXPLBUF;
- }
- saved_num_playlist = num_playlist;
- fclose(fp);
- return 1;
- }
-